package com.jvm.study.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.util.List;

/**
 * created by YDW
 */
@RestController
@RequestMapping("/jvm")
public class JvmController {

    @Value("${jvm.app}")
    private String  appid;

    public String getAppid() {
        return appid;
    }

    public void setAppid(String appid) {
        this.appid = appid;
    }

    /**
     * 通过mxbean方式获取使用的垃圾回收器
     * @return
     */
    @RequestMapping(value = "/get-jvm-info")
    public String getJvmInfo() {
        List<GarbageCollectorMXBean> list= ManagementFactory.getGarbageCollectorMXBeans();

        StringBuffer sb=new StringBuffer();
        list.forEach(item -> sb.append(item.getName()+"\n"));
        sb.append(appid);
        return sb.toString();
    }

    /**
     * jvm的死锁检测 使用工具jvisualvm来调试
     * 死锁的形成 通过重入锁别锁同一个对象已经获取另一个对象
     */
    @RequestMapping(value="/jvm-lock")
    public void jvmLock(){
        TestLock testLock=new TestLock();
        ThreadLock lock=new ThreadLock(testLock);
        ThreadLock2 lock2=new ThreadLock2(testLock);
        lock.start();
        lock2.start();
    }

    public class ThreadLock extends  Thread{

        private  TestLock lock;

        public ThreadLock(TestLock lock){
            this.lock=lock;
        }

        @Override
        public void run() {
            lock.left();
        }
    }

    public class ThreadLock2 extends  Thread{

        private  TestLock lock;

        @Override
        public void run() {
            lock.right();
        }
        public ThreadLock2(TestLock lock){
            this.lock=lock;
        }
    }

    public class  TestLock{
        private  final Object obj1=new Object();
        private  final Object obj2=new Object();


        public void right(){
            synchronized (obj1){
                try {
                    Thread.sleep(2000);
                    System.out.println("释放obj1");
                    synchronized (obj2){
                        System.out.println("释放obj2");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }

        public void left(){
            synchronized (obj2){
                try {
                    Thread.sleep(2000);
                    System.out.println("释放obj2");
                    synchronized (obj1){
                        System.out.println("obj1");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}
